#include <driver/view/keyboard.h>
#include <driver/view/msg.h>
#include <driver/view/hal.h>
#include <sys/input.h>
#include <os/driver.h>
#include <os/driver.h>
#include <lib/unistd.h>
#include <lib/stdio.h>
#include <lib/stdint.h>
#include <lib/stddef.h>

static int KeyboardKeyUp(int code);
static int KeyboardKeyDown(int code);

view_keyboard_t view_keyboard;

static int KeyboardSpecialKey(int code, int press)
{
    if (code == KEY_TAB)
    {
        if (view_keyboard.key_modify & VIEW_KMOD_ALT_L || view_keyboard.key_modify & VIEW_KMOD_ALT_R)
        {
            if (press)
            {
                KPrint("[keyboard][alt+tab] switch windows!\n");
            }
            return 1;
        }
    }
    return 0;
}

int ViewKeyboardInit()
{
    if (ViewKeyboardOpen(&view_keyboard) < 0)
    {
        KPrint("[view] open keyboard err\n");
        return -1;
    }
    view_keyboard.ledstatus = 0;
    view_keyboard.key_modify = 0;

    view_keyboard.keydown = KeyboardKeyDown;
    view_keyboard.keyup = KeyboardKeyUp;
    view_keyboard.virtual_mouse = -1;
    return 0;
}

int ViewKeyboardExit()
{
    view_keyboard.keydown = NULL;
    view_keyboard.keyup = NULL;
    ViewKeyboardClose(&view_keyboard);
}

static int KeyboardKeyUp(int code)
{
    //KPrint("view keyboard up %x\n", code);

    switch (code)
    {
    case KEY_LSHIFT:
        view_keyboard.key_modify &= ~VIEW_KMOD_SHIFT_L;
        break;
    case KEY_RSHIFT:
        view_keyboard.key_modify &= ~VIEW_KMOD_SHIFT_R;
        break;
    case KEY_LALT:
        view_keyboard.key_modify &= ~VIEW_KMOD_ALT_L;
        break;
    case KEY_RALT:
        view_keyboard.key_modify &= ~VIEW_KMOD_ALT_R;
        break;
    case KEY_LCTRL:
        view_keyboard.key_modify &= ~VIEW_KMOD_CTRL_L;
        break;
    case KEY_RCTRL:
        view_keyboard.key_modify &= ~VIEW_KMOD_CTRL_R;
        break;
    default:
        break;
    }

    if (KeyboardSpecialKey(code, 0))
        return -1;

    view_msg_t msg;
    ViewMsgHeader(&msg, VIEW_MSG_KEY_UP, VIEW_TARGE_NONE);
    ViewMsgData(&msg, code, view_keyboard.key_modify, 0, 0);
    ViewPutGlobalMsg(&msg);
    return 0;
}

static int KeyboardKeyDown(int code)
{
    //KPrint("view keyboard down %x\n", code);
    if (code == KEY_NUMLOCK) // numlock
    {
        if (view_keyboard.key_modify & VIEW_KMOD_NUM)
        {
            view_keyboard.key_modify &= ~VIEW_KMOD_NUM;
        }
        else
        {
            view_keyboard.key_modify |= VIEW_KMOD_NUM;
        }
    }

    if (code == KEY_CAPSLOCK) // cpas lock
    {
        if (view_keyboard.key_modify & VIEW_KMOD_CAPS)
        {
            view_keyboard.key_modify &= ~VIEW_KMOD_CAPS;
        }
        else
        {
            view_keyboard.key_modify |= VIEW_KMOD_CAPS;
        }
    }

    switch (code) // ctrl,alt,shift
    {
    case KEY_LCTRL:
        view_keyboard.key_modify |= VIEW_KMOD_CTRL_L;
        break;
    case KEY_RCTRL:
        view_keyboard.key_modify |= VIEW_KMOD_CTRL_R;
        break;
    case KEY_LSHIFT:
        view_keyboard.key_modify |= VIEW_KMOD_SHIFT_L;
        break;
    case KEY_RSHIFT:
        view_keyboard.key_modify |= VIEW_KMOD_SHIFT_R;
        break;
    case KEY_LALT:
        view_keyboard.key_modify |= VIEW_KMOD_ALT_L;
        break;
    case KEY_RALT:
        view_keyboard.key_modify |= VIEW_KMOD_ALT_R;
        break;
    default:
        break;
    }

    if (KeyboardSpecialKey(code, 1))
        return -1;

    // send msg
    view_msg_t msg;
    ViewMsgHeader(&msg, VIEW_MSG_KEY_DOWN, VIEW_TARGE_NONE);
    ViewMsgData(&msg, code, view_keyboard.key_modify, 0, 0);
    ViewPutGlobalMsg(&msg);
    return 0;
}
